package com.ymh.git.thread.juc.account;

import com.ymh.git.thread.juc.SleepTools;

/**
 * Created by aivin on 2018/11/1.
 * 线程安全的转账类的实现
 */
public class SafeOperate implements ITransfer {

    private static Object tieLock = new Object();//加时赛锁


    @Override
    public void transfer(UserAccount from, UserAccount to, int amount) {

        int fromHash = System.identityHashCode(from);//转出账户的hash值
        int toHash = System.identityHashCode(to);//转入账户的hash值

        //先锁hash值小的，再锁hash大的
        if (fromHash < toHash) {

            synchronized (from) { //先锁转出账户
                System.out.println(Thread.currentThread().getName() + " get " + from.getName());
                SleepTools.ms(100);
                synchronized (to) { //在锁转入账户
                    System.out.println(Thread.currentThread().getName() + " get " + to.getName());
                    from.outMoney(amount);
                    to.inMoney(amount);
                    System.out.println(from);
                    System.out.println(to);
                }
            }

        } else if (toHash < fromHash) {

            synchronized (to) { //先锁转入账户
                System.out.println(Thread.currentThread().getName() + " get " + to.getName());
                SleepTools.ms(100);
                synchronized (from) { //再锁转出账户
                    System.out.println(Thread.currentThread().getName() + " get " + from.getName());
                    from.outMoney(amount);
                    to.inMoney(amount);
                    System.out.println(from);
                    System.out.println(to);
                }
            }

        } else {
            synchronized (tieLock) {
                synchronized (to) { //先锁转入账户
                    synchronized (from) { //在锁转出账户
                        from.outMoney(amount);
                        to.inMoney(amount);
                        System.out.println(from);
                        System.out.println(to);
                    }
                }
            }

        }
    }
}
